﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;

namespace AEM.Controls
{
    public partial class Histogram : UserControl
    {

        public object HistogramData
        {
            get { return (object)GetValue(HistogramDataProperty); }
            set { SetValue(HistogramDataProperty, value); }
        }

        public static readonly DependencyProperty HistogramDataProperty =
            DependencyProperty.Register("HistogramData", typeof(object), typeof(Histogram),
            new UIPropertyMetadata(null, new PropertyChangedCallback(HistogramDataChanged)));

        /// <summary>
        /// 获取和设置直方图横坐标上每一个刻度的宽度。
        /// </summary>
        public double TickMarkWidth
        {
            get { return (double)GetValue(TickMarkWidthProperty); }
            set { SetValue(TickMarkWidthProperty, value); }
        }

        public static readonly DependencyProperty TickMarkWidthProperty =
            DependencyProperty.Register("TickMarkWidth", typeof(double), typeof(Histogram), new UIPropertyMetadata(0.0d));

        /// <summary>
        /// 获取和设置直方图中数据的最大值，因为我们希望在直方图的可视区域里面显示所有的矩形，
        /// 获取数据的最大值和最小值之后，其他的值我们可以按照比例放置，这样就能显示直方图中所有的数据了。
        /// 之所以设置成internal，是因为我们希望在同一个Assembly里面的Converter可以访问，但是不期望用户代码
        /// 能够访问到他们--反射除外。
        /// </summary>
        internal double Maximum = 0.0d;
        internal double Minimum = 0.0d;

        /// <summary>
        /// 因为我们打算支持很多种不同的数据，例如数组，Dictionary以及其他的可以解释成
        /// 键值对的数组，所以直方图内部最好有一个统一格式的数据结构来表示这些不同的数据。
        /// 至于数据格式之间的转换问题，我们可以通过采用Adapter模式来做。
        /// </summary>
        internal class HistogramDataObject
        {
            public object Category { get; set; }
            public string Color { get; set; }
            public double Value { get; set; }
        }

        public Histogram()
        {
            InitializeComponent();
            ObjectDataProvider provider = FindResource("histogramSelfInstance") as ObjectDataProvider;
            provider.ObjectInstance = this;
            Status[0] = (string)this.TryFindResource("Fault");
            Status[1] = (string)this.TryFindResource("Fire");
            Status[2] = (string)this.TryFindResource("Earthquake");
            Status[3] = (string)this.TryFindResource("CageAlarm");
            Status[4] = (string)this.TryFindResource("ConverterAlarm");

        }

        private static void HistogramDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Histogram histogram = sender as Histogram;
            Debug.Assert(histogram != null);

            if (e.NewValue is Array)
                PopulateArray(histogram, e);
            else
                throw new NotImplementedException("Supports for objects other than Dictionary and Array are not implemented yet!");
        }
        //fault fire earthquake CageAlarm ConverterAlarm
        private static string[] Colors = new string[] { "#FFFF3D3D", "#FFFF1BEF", "#FFFFFF1B", "#FFA479FF", "#FF8EEBEB" };
        private static string[] Status = new string[5];

        private static void PopulateArray(Histogram histogram, DependencyPropertyChangedEventArgs e)
        {
            Array array = e.NewValue as Array;
            Debug.Assert(array != null);
            Trace.WriteLineIf(array.Rank < 1 || array.Rank > 2, "Warning, multiple dimentional array is treated as 1-D array");

            List<HistogramDataObject> histogramDataObjects = new List<HistogramDataObject>();

            foreach (double[] a in array)
            {
                int index = -1;
                switch ((Data.Enum.LiftStatus)a[0])
                {
                    case Data.Enum.LiftStatus.Fault:
                        index = 0;
                        break;
                    case Data.Enum.LiftStatus.Fire:
                        index = 1;
                        break;
                    case Data.Enum.LiftStatus.IsEarthquaked:
                        index = 2;
                        break;
                    case Data.Enum.LiftStatus.CageAlarm:
                        index = 3;
                        break;
                    case Data.Enum.LiftStatus.ConverterAlarm:
                        index = 4;
                        break;
                }
                if (index != -1)
                {
                    histogramDataObjects.Add(new HistogramDataObject()
                                            {
                                                Color = Colors[index],
                                                Category = Status[index],
                                                Value = ((IConvertible)a[1]).ToDouble(Thread.CurrentThread.CurrentUICulture)
                                            });
                }
            }

            // 重新计算直方图数据的范围
            histogram.Maximum = histogramDataObjects.Max(h => h.Value);
            histogram.Minimum = histogramDataObjects.Min(h => h.Value);
            // 计算每一个刻度的宽度
            double tickWidth = histogram.ActualWidth / (histogramDataObjects.Count + 1);
            histogram.TickMarkWidth = tickWidth > 1 ? tickWidth : 1;
            // 强制直方图更新视图
            histogram.DataContext = histogramDataObjects;
        }

        private static void PopulateDictionary(Histogram histogram, DependencyPropertyChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

    }

}


